const { execSync } = require("child_process");
const ffi = require('@lwahonen/ffi-napi');
const ref = require('@lwahonen/ref-napi');
const iconv = require('iconv-lite');

let voidPointerType = ref.refType(ref.types.void);
let cStringPointerType = ref.refType(ref.types.CString);
let user32 = ffi.Library('user32.dll', {
    'EnumWindows': ['int', [voidPointerType, 'int32']],
    'EnumChildWindows': ['int', ['int32', voidPointerType, 'int32']],
    'GetClassNameA': ['int', ['int', 'string', 'int']],
    'GetWindowTextA': ['long', ['long', cStringPointerType, 'long']],
    'GetWindowThreadProcessId': ['int', ['int', 'pointer']],
    'PostMessageW': ['bool', ['long', 'long', 'long', 'long']],
});
let kernel32 = ffi.Library('kernel32.dll', {
    'OpenProcess': ['int', ['int', 'bool', 'int']],
    'CloseHandle': ['int', ['int']],
    'QueryFullProcessImageNameW': ['int', ['pointer', 'int', 'pointer', 'pointer']],
});
// let psapi = ffi.Library('psapi.dll', {
//     'GetModuleFileNameExA': ['int', ['int', 'int', 'string', 'int']]
// });

let serverProcessId
const list = []
const subList = []
let getm2serverClass = ffi.Callback('int', [
    'int32',
    'int32'
], function (p1, p2) {
    let WindowText = GetWindowTextA(p1);
    let ClassName = GetClassNameA(p1);
    let WindowThreadPId = GetWindowThreadProcessId(p1);
    if (WindowThreadPId === 0 || WindowThreadPId === 4 || !WindowText) {
        return 1;
    }

    if (WindowText.includes("翎风引擎控制台") || serverProcessId == WindowThreadPId || p1 == 66966) {
        list.push({
            pid: WindowThreadPId,
            path: WindowText,
            hwnd: p1,
            ClassName
        });
    } else {
        // console.log(serverProcessId, WindowThreadPId, p1, ClassName, WindowText);
    }

    // if (WindowThreadPId === m2serverPID && (ClassName === 'TFrmMain' || ClassName === 'TfrmMain')) {
    //     console.log("---WindowText------m2serverPID-------");
    //     hwnd = p1;
    // }
    // if (WindowText.search(/m2|控制/gi) > -1 && ClassName === 'TfrmMain' || ClassName === 'WTWindow') {
    //     console.log("控制器----------------");

    //     user32.EnumChildWindows(hwnd, getm2serverChildClass, 0);
    // }
    return 1;
});

let getm2serverChildClass = ffi.Callback('int', [
    'int32',
    'int32'
], function (p1, p2) {
    let ClassName = GetClassNameA(p1);
    let WindowThreadPId = GetWindowThreadProcessId(p1);
    let WindowText = GetWindowTextA(p1);
    // if (WindowThreadPId === m2serverPID && (ClassName === 'TFrmMain' || ClassName === 'TfrmMain')) {
    //     hwnd = p1;
    // }
    // console.log("---Child---", ClassName, WindowText, WindowThreadPId);
    if (WindowText.includes("无限版")) {
        // console.log("-------无限版---", ClassName, WindowText, WindowThreadPId);
        // subList.push({ pid: WindowThreadPId, path: WindowText, hwnd: p1, ClassName });
    }
    if (ClassName === 'TFrmMain' || ClassName === 'TFormMain') {
        console.log("-------TFrmMain---", ClassName, WindowText, WindowThreadPId);
        subList.push({ pid: WindowThreadPId, path: WindowText, hwnd: p1, ClassName });
    } else {
        // console.log("---Child---", ClassName, WindowText, WindowThreadPId);
    }
    return 1;
});
function GetWindowTextA(p1) {
    let alloc = Buffer.alloc(255);
    user32.GetWindowTextA(p1, alloc, 255);
    let from = Buffer.from(iconv.decode(alloc, 'gbk'));
    let readCString = ref.readCString(from, 0);
    return readCString;
};
function GetClassNameA(p1) {
    let alloc = Buffer.alloc(255);
    user32.GetClassNameA(p1, alloc, 255);
    let from = Buffer.from(iconv.decode(alloc, 'gbk'));
    let readCString = ref.readCString(from, 0);
    return readCString;
};
function GetWindowThreadProcessId(p1) {
    let alloc = Buffer.alloc(8);
    user32.GetWindowThreadProcessId(p1, alloc);
    let readUint32LE = alloc.readUint32LE(0);
    return readUint32LE;
};

// 根据进程名获取 PID 和路径
function getProcessInfoByName(processName) {
    const command = `wmic process where name="${processName}" get processid,executablepath,name /format:csv`;
    const output = execSync(command, { encoding: "utf-8" });

    // 解析 CSV 输出
    const lines = output.trim().split("\r\n");

    if (lines.length < 2) {
        return [];
    }

    const result = [];
    const headers = lines[0].split(",").map((h) => h.trim());

    for (let i = 1; i < lines.length; i++) {
        const values = lines[i].split(",");
        const entry = {};
        headers.forEach((header, index) => {
            entry[header] = values[index]?.trim();
        });
        result.push(entry);
    }

    return result;
}

function getProcessName(processID) {
    try {
        serverProcessId = processID

        user32.EnumWindows(getm2serverClass, 0);
        list.forEach((element, i) => {
            const cmd = 4 + i
            const result = user32.PostMessageW(element.hwnd, 273, cmd, 0);
            console.log(result, element.pid, element.hwnd, element.path, element.ClassName, cmd);
            user32.EnumChildWindows(element.hwnd, getm2serverChildClass, 0);
        });
        subList.forEach((element, i) => {
            const cmd = 4 + i
            const result = user32.PostMessageW(element.hwnd, 273, cmd, 0);
            console.log(result, element.pid, element.hwnd, element.path, element.ClassName, cmd);
        });


        // const PROCESS_QUERY_INFORMATION = 0x0400;
        // const PROCESS_VM_READ = 0x0010;

        // const OPENPROCESS = kernel32.OpenProcess(1040, false, processID);
        // if (!OPENPROCESS) {
        //     console.error('无法打开进程');
        //     return null;
        // }
        // console.log("---3333---");
        // const MAX_PATH = 260;
        // const buffer = Buffer.alloc(MAX_PATH * 2); // 宽字符缓冲区
        // console.log("---1111---");
        // const size = ref.alloc('uint32', MAX_PATH);
        // console.log("---32432---");
        // // 使用 QueryFullProcessImageNameW 获取进程路径
        // const result = kernel32.QueryFullProcessImageNameW(OPENPROCESS, 0, buffer, size);
        // if (result === 0) {
        //     console.error('无法获取进程路径');
        //     kernel32.CloseHandle(OPENPROCESS);
        //     return null;
        // }
        // console.log("------");

        // const path = buffer.toString('ucs2').replace(/\0/g, '');
        // kernel32.CloseHandle(OPENPROCESS);

        // console.log(path);


        // const OPENPROCESS = kernel32.OpenProcess(1040, false, processID);
        // let alloc = Buffer.alloc(255);
        // psapi.GetModuleFileNameExA(OPENPROCESS, 0, alloc, 255);
        // let readCString = ref.readCString(Buffer.from(iconv.decode(alloc, 'gbk')), 0);
        // kernel32.CloseHandle(OPENPROCESS);
        // console.log("readCString:", readCString);
        // return readCString;
    } catch (error) {
        console.log(error);

    }
};


module.exports = {
    getProcessInfoByName, getProcessName
};